/*
 * CppHighlighter.java  0.4.0 / Oct 23, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swingx.text.code;

import com.cute4j.swing.graphics.Color;
import com.cute4j.swing.text.CharacterFormat;
import com.cute4j.swing.text.TextHighlighter;

/**
 * C/C++ Syntax Highlighter.
 * <p>
 *   <tt>NOTE: This is an ad hoc implementation.</tt>
 * </p>
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class CppHighlighter extends TextHighlighter {

// Private Fields. -------------------------------------------------------------

  private final CharacterFormat keywordFormat;
  private final CharacterFormat commentFormat;
  private final CharacterFormat stringFormat;
  private final CharacterFormat macroFormat;
  private CppScanner cppScanner;
  private int lastBlockStart;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new JavaHighlighter object.
   */
  public CppHighlighter() {
    keywordFormat = new CharacterFormat();
    keywordFormat.setColor(new Color(0, 0, 113));
    keywordFormat.setFontBold(true);
    commentFormat = new CharacterFormat();
    commentFormat.setColor(new Color(0, 113, 0));
    stringFormat = new CharacterFormat();
    stringFormat.setColor(new Color(0, 0, 208));
    macroFormat = new CharacterFormat();
    macroFormat.setColor(new Color(113, 0, 0));
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  protected void highlightBlock(int blockStart, String blockText) {
    if ((cppScanner == null) || (blockStart < lastBlockStart)) {
      cppScanner = new CppScanner(blockText);
    } else {
      cppScanner.continueScan(blockText);
    }
    try {
      CppToken cppToken = cppScanner.nextToken();
      while (cppToken != null) {
        switch (cppToken.type) { // NOPMD
          case CppToken.KEYWORD:
            setFormat(cppToken.start, cppToken.length, keywordFormat);
            break;
          case JavaToken.COMMENT_END:
            setFormat(cppToken.start, cppToken.length, commentFormat);
            break;
          case CppToken.INLINE_COMMENT:
             // falls through
          case CppToken.EOCB:
            setFormat(cppToken.start, cppToken.length, commentFormat);
            return;
          case CppToken.QT_EXTENSION:
             // falls through
          case CppToken.STRING:
             // falls through
          case CppToken.NUMBER:
            setFormat(cppToken.start, cppToken.length, stringFormat);
            break;
          case CppToken.MACRO:
            setFormat(cppToken.start, cppToken.length, macroFormat);
            break;
        }
        cppToken = cppScanner.nextToken();
      }
    } catch (Throwable t) { // NOPMD
      // empty catch block
    }
    blockStart = lastBlockStart;
  }

}
